//****************************************/
//* mElements  12 2011                   */
//* Riku Maikola rpm@ac-mapa.org         */
//****************************************/

#include "../mElements.h"

mPoint eCircle::p1()
{
    return at(0);
};
mPoint eCircle::p2()
{
    return at(1);
};
mPoint eCircle::cp()
{
    return at(2);
};


//********************************************************************************************************//
//**                //\\    element boxing  13.12.2012
//**               //__\\
//**              //    \\
//********************************************************************************************************//
void eCircle::cArea()
{
    ClearArea();

    test(cp().x-r,cp().y+r);
    test(cp().x+r,cp().y-r);
}


//***********************************************************************************//
bool eCircle::Match(eCircle ci)
{

    if( cp().Match(ci.cp()) && AER(r,ci.r))return true;
    return false;
}
//***********************************************************************************//
//**                                                                               **//
//**          get readbl data                         18.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
wxString eCircle::Info()
{
    return wxString::Format( _("circle cp()(%1.3f,%1.3f) r(%1.3f)"),cp().x,cp().y,r);
}


//***********************************************************************************//
//**                                                                               **//
//**          Connection  jump                       13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
bool eCircle::Connection(mPoint *point,mPoint *center,int *type)
{
    printf("NOT SUPPORTED CONNECTION TYPE -CIRCLE-\n");
    return false;
}
//***********************************************************************************//
//**                                                                               **//
//**          get Distance from xy location          13.12.2012                    **//
//**                                                                               **//
double eCircle::Distance(double X,double Y)
{
    double D = r - Distance2D(X,Y,cp().x,cp().y);
    if(D<0)return -D;
    return D;
}
//***********************************************************************************//
//**                                                                               **//
//**          get cirle area collison points         13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
bool eCircle::Intersection(mPointArray *A,eLine line)
{
    return line.Intersection( A,eC(cp(),r));
}

bool eCircle::Intersection(mPointArray *A,eArc arc)
{
    return arc.Intersection( A,eC(cp(),r));
}
//******************** eCircle    **************************************//
bool eCircle::Intersection(mPointArray *A,eCircle cir)
{
    uint size= A->size();
    double d=cp().GetDistanceXY(cir.cp());
    double dx=((d*d)-(cir.r*cir.r)+(r*r))/(d*2);
    double dy=sqrt((r*r)-(dx*dx));

    if(dx>r || (-dx)>r)return false;

    double da = cp().GetDirectionXY(cir.cp());

    mPoint mp,t1,t2;
    mp = cp().GetFromPoint(da,dx);

    t1 = mp.GetFromPoint(da+1.570796325,dy);
    t2 = mp.GetFromPoint(da-1.570796325,dy);

    A->Add(t1,true);
    A->Add(t2,true);

    if(size<A->size())return true;
    return false;
}

bool eCircle::Intersection(mPointArray *A,eRay ray)
{
    double dx = ray.p2().x - ray.p1().x;
    double dy = ray.p2().y - ray.p1().y;
    double a = dx * dx + dy * dy;
    double b = 2 * (dx * (ray.p1().x - cp().x) + dy * (ray.p1().y - cp().y));
    double c = cp().x * cp().x + cp().y * cp().y;
    c += ray.p1().x * ray.p1().x + ray.p1().y * ray.p1().y;
    c -= 2 * (cp().x * ray.p1().x + cp().y * ray.p1().y);
    c -= r * r;
    double bb4ac = b * b - 4 * a * c;

    //Not intersecting
    bool answer = false;
    if(bb4ac<0)
    {
        if(Distance(ray.p1().x,ray.p1().y)<0.0001)
        {
            A->Add(ray.p1(),true);
             answer =true;
        }
        if(Distance(ray.p2().x , ray.p2().y)<0.0001)
        {
            A->Add(ray.p2(),true);
            answer =true;
        }
        return answer;
    }
    else
    {
        double mu = (-b + sqrt( b*b - 4*a*c )) / (2*a);
        double ix1 = ray.p1().x + mu*(dx);
        double iy1 = ray.p1().y + mu*(dy);
        mu = (-b - sqrt(b*b - 4*a*c )) / (2*a);
        double ix2 = ray.p1().x + mu*(dx);
        double iy2 = ray.p1().y + mu*(dy);
        A->Add(mP(ix1,iy1),true);
        A->Add(mP(ix2,iy2),true);
        return true;
    }
    return false;
}
//************************************************************************************************//
//**                                                                                            **//
//**                        ToArray                                                             **//
//**                                                                                            **//
//************************************************************************************************//
mPointArray eCircle::ToArray(double accuracy)
{
    mPointArray P;
    double am=TAU;
    if(r>accuracy)
        am = acos((r-accuracy)/r)*2;

    P.Add(p1());
    for(double a3=0; a3<TAU; a3=a3+am)
    {
        P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
        P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
    }
    P.Add(p2());
    return P;

}
//************************************************************************************************//
//**                                                                                            **//
//**                        GLOBAL..                                                            **//
//**                                                                                            **//
//************************************************************************************************//
eCircle eC(mPoint cp,double r,wxString L)
{
    eCircle circle;
//    circle.layer=L;
    circle.r = r;
    circle.a1 = 0;
    circle.a2 = TAU;
    circle.flag = false;
    circle.push_back( mP(cp.x+r,cp.y) );
    circle.push_back( mP(cp.x+r,cp.y) );
    circle.push_back( mP(cp.x,cp.y,cp.z) );

    circle.cArea();
    return circle;
}
